package com.hdl.server.host;

import com.hdl.server.classload.MyClassLoader;
import com.hdl.server.context.Context;
import com.hdl.servlet.HttpServlet;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * 类名 ContextBuilder
 * 描述 解析context标签
 *
 * @author hedonglin
 * @version 1.0
 * @date 2020/5/31 18:04
 */
public class HostBuilder {
    public static HostBuilder builder(){
        return new HostBuilder();
    }

    public List<Host> parseHost(InputStream inputStream) throws DocumentException, IOException {
        List<Host> hostResult = new ArrayList<>();

        Document document = new SAXReader().read(inputStream);
        List<Element> contexts = document.selectNodes("//Context");

        if (contexts.size() == 0){
            // 直接解析Host标签，并使用其appBase作为项目存放路径
            List<Element> hosts = document.selectNodes("//Host");

            for (Element element : hosts) {
                // 这里只加载host下的appBase
                String appBase = element.attributeValue("appBase");

                // 加载classpath下面的webapps文件夹,并存储Context
                List<Context> contextList = doParseContext(appBase);

                Host host = new Host(appBase, contextList);
                hostResult.add(host);
            }
        }
        return hostResult;
//        for (Element context : contexts) {
//            context.attributeValue("docBase");
//        }
    }

    /**
     * 获取指定目录下的目录
     * @param path 路径
     */
    private List<Context> doParseContext(String path) throws IOException {
        List<Context> contexts = new ArrayList<>();
        // 获取包路径
        String courseFile = (System.getProperty("user.dir") + "/Minicat/" + path).replaceAll("/", "\\\\");
        File files = new File(courseFile);
        if (!files.exists()){
            System.out.println("需要加载的server.xml不存在");
            return Collections.emptyList();
        }
        for (File file : files.listFiles()) {
            final Context context = new Context();
            if (file.isDirectory()) {
                // 判断WEB-INF下面是否有web.xml
                File[] listFiles = file.listFiles();
                for (File listFile : listFiles) {
                    boolean b = listFile.getName().equalsIgnoreCase("WEB-INF");
                    if (b){
                        final File[] webInfs = listFile.listFiles();
                        for (File webInf : webInfs) {
                            if (webInf.getName().equalsIgnoreCase("web.xml")){
                                // 解析web.xml,读取servlet的信息
                                if (webInf.isFile()){
                                    Map<String, HttpServlet> servletMap = loadServlet(webInf);
                                    context.setServletMap(servletMap);
                                }

                            }
                        }
                    }
                }
                context.setContext(file.getAbsolutePath());
                // 加入应用名称
                if (file.getName().equalsIgnoreCase("ROOT")){
                    context.setPath("/");
                }else {
                    context.setPath("/" + file.getName());
                }
                contexts.add(context);
            }
        }

        return contexts;

    }


    /**
     * 加载解析web.xml，初始化Servlet
     */
    private Map<String, HttpServlet> loadServlet(File file) {
        Map<String, HttpServlet> servletMap = new HashMap<>();
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(file);
            Element rootElement = document.getRootElement();

            List<Element> selectNodes = rootElement.selectNodes("//servlet");

            for (int i = 0; i < selectNodes.size(); i++) {
                Element element =  selectNodes.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                // <servlet-class>server.LagouServlet</servlet-class>
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();


                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /lagou
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                try {
                    servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
                } catch (ClassNotFoundException e) {
                    MyClassLoader myClassLoader = new MyClassLoader();

                    String servletPath = servletClass.replaceAll("\\.", "\\\\");
                    String fullServletPath = file.getParentFile().getAbsolutePath() + "\\" + "classes\\" + servletPath + ".class";
                    byte[] bytes = Files.readAllBytes(Paths.get(fullServletPath));

                    Class<?> aClass = myClassLoader.findClass(servletClass, bytes);
                    Object o = aClass.newInstance();
                    servletMap.put(urlPattern, (HttpServlet)o );
                }

            }
        } catch (DocumentException | IllegalAccessException | InstantiationException | IOException e) {
            e.printStackTrace();
        }
        return servletMap;

    }




}
